perm filename MESSAG.WRU[SYS,HE] blob
sn#004173 filedate 1972-06-01 generic text, type T, neo UTF8
00100 %TOP,,HAND-EYE SYSTEM PART II, ,1-1
00200
00300
00400
00500
00600
00700
00800
00900
01000
01100
01200
01300
01400
01500
01600 SYSTEM MANUAL FOR HAND-EYE HACKERS
01700
01750 PART I. [HAND.WRU]
01800 PART II. MESSAGE PROCEDURES [MESSAG.WRU]
01900 SECTION 1. AN EXAMPLE
02000 SECTION 2. CALLS
02100 SECTION 3. ANOTHER EXAMPLE
02200 SECTION 4. TEMPLATES
02250 SECTION 5. ERROR MESSAGES
02300 PART III. MONITOR [MONITR.WRU]
00100 1.0 MESSAGE PROCEDURES
00200
00300 There must be a mechanism for communicating among the various
00400 modules of the hand-eye system. Since each of these modules is
00500 talking to a common second segment, it makes sense to establish the
00600 communication paths in that segment.
00700
00800 We want to be able to send messages to each other which have
00900 SAIL-like data associated with them. We do not want to convert all
01000 our message data to some symbolic form and (say) write a disk file
01100 with that text, but instead to pass data of all types (sets, items,
01200 arrays, integers, reals, etc.) in a reasonably efficient manner. At
01300 the same time, we want to prevent the programs from having to do
01400 explicit type-checking of message data, or explicit "get this datum"
01500 operations.
01600
01700 A mechanism which meets these requirements is already in SAIL, namely
01800 actual parameter passing to procedures. A message , then, will
01900 consist of a name of a procedure and a parameter list to pass to that
02000 procedure for evaluation, together with some bookkeeping information.
02100 The user is allowed to specify a symbolic source of the message and a
02200 symbolic destination for the message. These names specify the module
02300 to be activated (i.e. the recipient of the message), and the source
02400 module.
02500
02600 So to review, we have implemented a mechanism for a user in one
02700 module to emit calls to procedures actually located in another
02800 module. The matching and passing of formal parameters is handled in
02900 much the same way as for ordinary procedures. Of course, the calling
03000 module must have declared the names and parameter lists of the
03100 procedures he is calling. These declarations will be in the hand eye
03200 definition tape, and look like ordinary procedure declarations,
03300 except that the words FORWARD MESSAGE appear:
03400
03500 FORWARD MESSAGE PROCEDURE TRANSFORM(INTEGER X;ITEM Y;REAL ARRAY Z);
03600
03700 Now let us shift attention to the module in which this procedure is
03800 actually located. We must provide a mechanism to allow this
03900 procedure to be evaluated for each "message" passed to it. We could
04000 arrange that whenever a message specifying the evaluation of some
04100 procedure was passed to a module, that module is interrupted, and the
04200 message request honored. But this is unthinkable, for many reasons.
04300 First, the module would like to control the priorities with which
04400 messages are evaluated. Second, the module might object to being
04500 suspended in the midst of a computation which has left an
04600 inconsistent view of the world in the module's data structures.
04700
04800 To rectify this, a module must specifically receive messages, and
04900 must request the evaluation of the specified procedure. The SAIL
05000 calls for doing this are described below.
05100
05200 Briefly, a module may look around in the list of messages in order to
05300 locate one destined for him. He may then request that the message be
05400 activated, i.e evaluate the procedure which is located in my module
05500 and which has the same name as the "procedure name" specified in the
05600 message. This evaluation is performed with the arguments as
05700 specified in the message. Normally, when the procedure exits, the
05800 message is acknowledged (i.e. the calling module may now determine
05900 that the message has completed).
06000
06100 When the user declares a procedure which is to process messages, he
06200 must precede that declaration with MESSAGE:
06300
06400 MESSAGE PROCEDURE TRANSFORM (INTEGER A;ITEM x;REAL ARRAY FOO);
06500
06600 followed by the procedure text. These procedures may be called by you
06700 in your own module in the normal way.
06800
06900
00100 1.0 An example
00200
00300 Let us briefly review by giving a very simple example. We have two
00400 modules, which we shall call symbolically CALL and ARITH. The module
00500 CALL wants to activate the message procedure TRANSFORM in the ARITH
00600 module. He does this by sending a message to ARITH, citing TRANSFORM
00700 as the procedure name, and giving the necessary paremeters. He wants
00800 to suspend his own execution until TRANSFORM has been executed in
00900 ARITH. So CALL says:
01000
01100 forward message procedure TRANSFORM (integer a; real array b);
01200 comment this is needed so that the procedure names and
01300 parameter types are known during compilation of
01400 the CALL module. These declarations will normally
01500 reside in the global definition tape.
01600
01700 integer mess;
01800 comment this will be explained below;
01900
02000 mess ← ISSUE ( 7,"CALL","ARITH", MESSAGE TRANSFORM (2,mine));
02100 comment This specifies a message. The names CALL and
02200 ARITH are the source and destination logical
02300 names respectively. The message described is
02400 TRANSFORM (2,mine). That is, 2 and mine will
02500 be the parameters supplied when TRANSFORM is
02600 executed in ARITH. The 7 is a code to ask that
02700 execution be suspended until the procedure
02800 TRANSFORM has finished its evaluation, and then
02900 to kill the message (erase all record of it);
03000
03100
03200 Now for the code in module ARITH which will process the message:
03300
03400 forward message procedure TRANSFORM(integer a;real array b);
03500 comment This is in the definition tape, as the
03600 definition in CALL above;
03700
03800 integer mess;
03900
04000 message procedure TRANSFORM (integer a; real array b);
04100 begin
04200 integer i,j;
04300 for i←1 step 1 until a do b[i]←b[i]*b[a-i+1];
04400 end;
04500
04600 comment This is the actual procedure text for TRANSFORM;
04700
04800
04900 comment .. in the main execution block of ARITH, we must
05000 examine the queue of messages sent to us, and
05100 then evaluate the appropriate procedure;
05200
05300 PUT_DATA (0,0,"ARITH");
05400 comment initialization -- described below;
05500
05600 while true do begin
05700 mess ← GET_ENTRY ('120,NULL,"ARITH",NULL);
05800 comment This waits for a message to arrive destined
05900 for ARITH. The unique descriptor of the
06000 message is placed in mess;
06100
06200 mess ← QUEUE ('600,mess);
06300 comment Now that we have gotten a message, we
06400 "activate" it (i.e. evaluate the procedure
06500 located in the ARITH module, and with the
06600 name and parameters specified in the message.
06700 When finished, we "acknowledge" completion of
06800 the message. This will allow CALL to
06900 resume computation (remember -- he requested
07000 to be suspended until TRANSFORM finished);
07100
07200 end;
07300
07400
07500
07600 This completes the simple example. There follows a fairly detailed
07700 description of the exact SAIL calls, followed by this same example,
07800 with slightly expanded comments. Then some templates are given to
07900 aid in putting together "standard" message procedure code.
00100 2.0 Detailed description of message procedure calls.
00200
00300 A queue is kept in the second segment which contains all messages. A
00400 message consists of a symbolic source identifier (10 chars max) a
00500 symbolic destination identifier (10 chars max), a message procedure
00600 name (10 chars max), and the parameter list which is to be supplied
00700 to that procedure when evaluated. Associated with each entry in the
00800 queue will be a unique number. The user will reference entries in
00900 the queue by this number.
01000
01100 Many of the calls on message handlers require a directive word. This
01200 word is made up from the following bits (all explained below):
01300
01400 DSEND '1
01500 DWAIT '2
01600 DKILL '4
01700 DSOURCE '10
01800 DDEST '20
01900 DNAME '40
02000 DWAITM '100
02100 DACT '200
02200 DACK '400
02300 DEVERY '2000
02400 DNOACT '4000
02500 DRETURN '40000
02600
02700 The calls which the user has available to manipulate queue entries:
02800
02900 1. Insert a thing into the queue.
03000
03100 integ. ← ISSUE (directive,source,destination,MESSAGE kkk(param list))
03200
03300 KKK is the message procedure name to be associated with this queue
03400 entry, and param list will be passed off for inclusion in the queue
03500 entry. A declaration for KKK was made in the user's program, and is
03600 assumed to be the same declaration that was used when the procedure
03700 was finally defined. Source and destination are the strings to be
03800 included as message identifiers. The directive bits say what to do
03900 with the entry --
04000 a. put it in the queue (assumed always).
04100 b. send it to the right guy (DSEND). If DNOACT is on, the
04200 recipient is not activated.
04300 c. wait for acknowledgment on completion (DWAIT).
04400 These directive bits may be OR'ed together, and will be processed, if
04500 on, in the order a,b,c. Integ will contain the unique number
04600 generated, and can be used to talk about this queue entry in the
04700 future.
04800
04900 2. Utility functions on things in the queue.
05000
05100 integ ← QUEUE (directive,unique number)
05200
05300 Directive specifies --
05400 a. send it (DSEND).
05500 b. wait for completion (DWAIT).
05600 c. activate the entry (DACT).
05700 d. acknowledge the entry (DACK).
05800 e. kill the entry (DKILL).If the message is sent to another
05900 module, killing is delayed until the message is
06000 acknowledged.
06100
06200 These are processed in the order a,b,c,d,e and may be OR'd together.
06300 If integ. is zero, there was no such queue entry. The interpretation
06400 of DSEND and DWAIT were discussed above. DACT specifies that the
06500 procedure named in the message should be evaluated. If that
06600 procedure is defined in your module, which it should be, it will be
06700 evaluated. DACK specifies that the message should be acknowledged.
06800 If the sender was waiting for completion of the message, he will now
06900 be allowed to proceed. If a sender was waiting for completion and you
07000 do not acknowledge, he will never be run again.
07100
07200 string ← GET_DATA (directive,unique number)
07300 PUT_DATA (directive,unique number,string)
07400 integ ← GET_BIT (unique number)
07500
07600 This is for looking into the message block and perhaps changing
07700 things. The directive may specify
07800 a. source identifier
07900 b. destination identifier
08000 c. message procedure name.
08100 The directive should be 1 for a, 2 for b, and 3 for c. Note that this
08200 is a non-standard use of the directive bits. If you say
08300 PUT_DATA(0,0,"string") then "string" is set as your logical name. If
08400 some other module sends a message with destination as "string", then
08500 you will be activated. A statement like this is REQUIRED for
08600 initializing the message system. If you say PUT_DATA(-1,JOBNUM,"")
08700 then the logical name and job number of the job with job numver
08800 JOBNUM will be removed . This is usually done only by the hand/eye
08900 monitor when it kills subjobs.
09000
09100 GET_BIT returns the bits associated with an entry in the message
09200 queue. Integer will contain the following bits:
09300 DSEND -- the message has been sent.
09400 DWAIT -- someone is waiting for completion of this message.
09500 DKILL -- this message is marked for killing when acknowledged.
09600 DACT -- this message is active (proc. being evaluated).
09700 DACK -- this message has been acknowledged.
09800
09900 3. Functions for searching the queue.
10000
10100 integ. ← GET_ENTRY (directive,source,destination,procedure name)
10200
10300 Where the directive specifies:
10400 a. find match on source (DSOURCE).
10500 b. find match on destination (DDEST).
10600 c. find match on procedure name (DNAME).
10700 (these a-c may be OR'd together in which case the
10800 AND of the conditions must obtain).
10900 d. if you don't find such a thing, wait for one (DWAITM).
10950 WARNING: As the second segment is now coded, you
10975 will only be awakened (from DWAITM or the interrupt
10987 routines) when a message specifies you as its
10993 destination.
11000 e. Continue even if DWAITM is set (DRETURN)
11100 (for use with interrupt routine only)
11200 f. look at every entry (DEVERY). Ordinarily, messages that
11300 are not sent or are already activated are not returned
11400 by GET_ENTRY. If DEVERY is on, all messages matching
11500 the conditions are returned.
11600 Integ. will have the unique number. If zero, no entry was found.
11700
11800
11900 set ← GET_SET (directive,source,destination,procedurename)
12000
12100 This is the same as GET_ENTRY, except that the set of possible
12200 matches is returned. If there is no match and DWAITM is on, we will
12300 wait! The unique message numbers are put in the set. This means
12400 that the set will be ordered by creation order of the messages. You
12500 will have to do CVN's on the things you get out of the set in order
12600 to get numbers to use as message numbers.
12700
12800
12900
13000
13100
13200 6. Parameters.
13300
13400 Of course there are some difficulties in making all types of
13500 parameters accessible to the called routine, since things in the
13600 caller's core image are not accessible to the called routine. So
13700 behold the catalog of things we will do for parameters:
13800
13900 a. Call by VALUE.
14000 a. algebraic things. This is easy, we just copy the
14100 algebraic value. Strings are included in this class.
14200 b. sets. Sets must contain solely global items. If necessary,
14300 the sets will be recopied into 2nd segment core.
14400 c. item. If global, ok, otherwise definitely not ok.
14500 d. itemvar. same as item. Note that if you are trying to
14600 pass a local item merely so that the called routine
14700 can obtain the datum, then why not pass the datum??
14800
14900 b. Call by REFERENCE.
15000 a. algebraic things. If the thing is a global of any kind,
15100 no cleverness need be invoked. If it is a local
15200 array, a copy will be made in the 2nd segment, and
15300 deleted after the message is ACTIVATED (no string
15400 arrays). If the thing is any other kind of non-
15500 global entity, the right thing will happen,
15600 but under no circumstances will the called procedure
15700 be able to alter the contents of that variable in your
15800 module. If you desire to return results, they may be
15900 returned in the global model.
16000 b. sets. If global, OK. If a local, the set is checked for
16100 non-global items and copied into 2nd segment, and
16200 deleted after activating, just as in arrays. Under no
16300 circumstances will any call
16400 by reference of a 1st segment thing cause that thing to
16500 be changed.
16600 c. itemvar -- if global, OK. If not, the thing is copied
16700 into the second segment and released after ACTIVATing.
16800
16900 b. RETURNS.
17000 Results of message procedures may of course be returned in the global
17100 model. There will also be some way of getting at the integer or real
17200 or itemvar result of the called procedure. Since this is a little
17300 messy to imbed in the ISSUE call, we may do that by providing some
17400 specific way of accessing the message results. [NOT IMPLEMENTED]
17500
17600
17700
17800
17900 7. Tracing.
18000
18100 There is a facility for tracing messages passed from one job to
18200 another. This facility is actually handled by the same program which
18300 handles the TTY-PTY operations (see section 4 below). Presently, a
18400 trace consists of a type-out at the controlling TTY of the form
18500
18600 time MESSAGE TRACE: source destination message_procedure_name args
18700
18800 where time is in milliseconds since midnight. Args is a list of
18900 argument data for the message procedure. There is one string of
19000 characters for each argument, seperated by blanks. Boolean, real,
19100 and integer arguments have their values printed (boolean prints as
19200 integer). For string arguments, the string is printed, surrounded by
19300 double quotes. Other arguments are not printed. Instead, a string
19400 of characters describing the data type of the argument is printed.
19500 The characters printed are:
19600
19700 I INTEGER (or BOOLEAN)
19800 F REAL (floating point)
19900 L LABEL
20000 S SET
20100 Lp leap array (things like SET ARRAY ITEMVAR ARRAY)
20200 St STRING
20300 It ITEM
20400 Iv ITEMVAR
20500 G GLOBAL
20600 A ARRAY
20700 R REFERENCE
20800 V VALUE
20900
21000 The details of the message tracing mechanism are as follows: There is
21100 a global variable (global in the LOADER sense, not in the SAIL sense)
21200 in the second segment called TRACING. If it is set non-zero, message
21300 tracing is enabled. Every time a message is "sent" by the message
21400 handler, a trace message is first sent to the tracing job. When the
21500 tracing message is acknowledged, the original message is finally
21600 "sent" to its prescribed destination. The tracing message is of the
21700 form
21800
21900 source: ""
22000 destination:"TRACE"
22100 message: TRACE ( integer message_number , pntr )
22200
22300 The message_number can be used to examine the queue for good
22400 information about the message being traced (i.e. the source,
22500 destination, name, parameters, etc.). Pntr points to good things in
22600 the second segment.
22700
22800
00100 3.0 An example of message procedures and calls.
00200
00300 CALL module :
00400
00500 forward message procedure TRANSFORM (integer a; real array b);
00600
00700 ......
00800
00900 comment Somewhere, module 1 needs to call TRANSFORM. He wants to
01000 pass arguments 2 and mine to the procedure. He wants
01100 to wait for the evaluation to finish before continuing
01200 any of his computation. He says:
01300
01400 mess ← ISSUE (7,"CALL","ARITH",MESSAGE TRANSFORM (2,mine));
01500
01600 comment This is a message from the symbolic CALL to the symbolic
01700 ARITH, and is a request for the evaluation of the
01800 procedure TRANSFORM. When the evaluation of TRANSFORM
01900 is complete, execution will continue with the next
02000 statement, and mess will contain the unique number
02100 associated with the message that was generated
02200 (this is useful in referring to the message if you
02300 desire to inquire as to the status of completion, etc.
02400 In this example, however, it is useless since we do not
02500 continue computation until TRANSFORM has completed, and
02600 the message has served its purpose).
02700
02800
02900 ARITH module:
03000
03100 forward message procedure TRANSFORM (integer a;real array b);
03200
03300 ......
03400 comment Now he actually defines the procedure:;
03500
03600 message procedure TRANSFORM (integer a;real array b);
03700 begin
03800 integer i,j;
03900 for i←1 step 1 until a do b[i]←b[i]*b[a-i+1];
04000 end;
04100
04200 ..... comment now in main execution block.;
04300
04400 PUT_DATA (0,0,"ARITH");
04500 comment only needs doing once;
04600
04700 mess ← GET_ENTRY ('120,NULL,"ARITH",NULL);
04800
04900 comment This waits for a message sent to symbolic destination ARITH.
05000 When such a message arrives, the unique number describing
05100 that message is stored in mess. Execution continues: ;
05200
05300 mess ← QUEUE('600,mess);
05400
05500 comment Now we actually activate the message. The procedure TRANSFORM
05600 is evaluated with arguments 2,mine (or actually a copy of mine).
05700 When the procedure returns, the message is acknowledged so that
05800 module 1 can resume processing (since he decided to wait for
05900 completion). Control in module 2 returns to the next statement:;
06000
06100 .......
06200
00100 4.0 Templates for message procedure protocol.
00200
00300
00400 First we give some protocols for ISSUEing message requests. We give
00500 the symbolic form of the directive to be used in the ISSUE call:
00600
00700 DSEND+DWAIT+DKILL -- normal "subroutine"-like call.
00800 You will be suspended until the destination module has
00900 processed and ACKNOWLEDGED this message. You should
01000 check with him or his code to be sure than an acknowledgement
01100 is generated. If it is not, you will wait a long, long
01200 time. The message is killed when done.
01300
01400 DSEND+DKILL -- "fork" call.
01500 You will continue execution immediately, and not wait
01600 for the destination module to to anything. However,
01700 he should eventually get around to ACKNOWLEDGing
01800 the message, at which time it will be killed.
01900
02000 DSEND -- "leave mail" call.
02100 This merely puts the message in the queue.
02200 The destination job can do with this as he likes.
02300 (This can be used for passing off several messages in
02400 a row -- they need never be actually ACTIVATED or
02500 ACKNOWLEDGED by the destination).
02600
02700
02800 Now we give similar protocols for answering the messages. If we rely
02900 on blind faith, and want to process each message as it arrives:
03000
03100 mess← GET_ENTRY (DDEST+DWAITM,"","MY NAME","");
03200
03300 Then, when this returns, we ACTIVATE and ACKNOWLEDGE the message:
03400
03500 mess ← QUEUE (DACT+DACK,mess);
03600 if mess=0 then type "error in messages to MY NAME" eom;
03700
03800 This will handle all messages ISSUEd with the first and second
03900 protocols listed above.
00100 5.0 ERROR MESSAGES
00150
00200 Below is a list of the error messages generated by the second segment
00300 message procedure routines. The errors will try to continue if
00400 requested to, but they should be considered fatal. (In other words,
00500 don't continue)
00600
00700 MESSAGE CONFUSION code is garbaged or second seg. bug
00800 ITEM MUST BE GLOBAL local item was seen as an argument.
00900 NO CORE FOR MESSAGE system is out of core
01000 THESE ARRAYS TOO COMPICATED tried to pass set or string array
01100 TOO MANY PARAMS over six arguments for procedure
01200 NO SUCH DESTINATION Message sent to non-ex job
01300 MAIL WAIT CONFLICT bug in second segment or core garbaged
01600 MAIL SCREW The system mail mechanism goofed
01610 or two jobs of the same name exist in
01655 the system.
01700 NO DIRECTIVE Queue called with no legal directive
01800 NO GET_ENTRY DIRECTIVE same
01900 GET_SET:NEED LEAP INITIALIZATION ran out of items
02000 LOGICAL NAME ALREADY DEFINED PUT_DATA(0,0,"name") has a name already
02100 defined for another job number. If
02150 you continue, the current job number
02175 is substituted for the old one (which
02187 may not be what you want).
02200 TOO MANY JOBS Tables have overflowed (16 jobs allowed)
02300 If you see this message, you might
02400 inquire of the system hackers where the
02500 other PTY came from.
02600 WHO ARE YOU?? You executed a GET_ENTRY procedure
02650 before doing your PUT_DATA
02750 initialization.
02800 YOUR MESSAGE DISAPPEARED The message you just activated was
02850 gobbled up by someone while you were
02950 executing it. This is legal but
03050 undesireable - let me know if
03150 it happens. It will continue automatically.
03200 MESSAGE SNATCHER This is the guy who is trying to kill the
03300 above message (if it will result in core
03400 lossage). You can continue from this
03500 message.
03600 VERSION # TOO LOW Subjob using PREAMB.SAI has the incorrect
03700 version number. Recompile it to get the
03800 current version of the preamble.
03900 VERSION # TOO HIGH Either the hand/eye monitor needs to be
04000 recompiled or you have a saved second
04100 segment which is too old.